﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace Sworm
{
    public class TypeAnalyzer
    {
        public virtual Func<object, object> GetDefaultToDbConverter(Type paramType)
        {
            return null;
        }

        public virtual Func<DbAccessor, object> GetFromDbConverter(Member member)
        {
            return null;
        }

        public virtual ColumnData SelectPrimaryKey(TableData table, out bool isAutoIncrement)
        {
            var matches = table.Columns.Select(c => new
            {
                col = c,
                att = c.Member.GetCustomAttributes(false).OfType<ColumnAttribute>().SingleOrDefault()
            })
                .Where(x => x.att != null)
                .Where(x => x.att.IsPrimaryKey)
                .ToList();

            if (matches.Count > 1)
            {
                throw new Sworm.InvalidMetadataException(
                    "cannot specify more than one primary key on " + table.ClassType.FullName);
            }
            var match = matches.SingleOrDefault();

            if (match != null)
            {
                isAutoIncrement = match.att.IsAutoIncrement;
                return match.col;
            }

            var pk = table.Columns.SingleOrDefault(c => c.Name.Unescaped.Equals("id", StringComparison.OrdinalIgnoreCase));
            if (pk != null)
            {
                isAutoIncrement = pk.Member.Type == typeof(int) || pk.Member.Type == typeof(long);
                return pk;
            }

            isAutoIncrement = false;
            return null;
        }

        public virtual void SimplifyColumnType(ref Type type)
        {
        }

        public virtual DbType? GetDbType(Member member)
        {
            return null;
        }

        public virtual string GetSqlColumnName(Member member)
        {
            return member.Name;
        }

        public virtual bool ShouldMapColumn(Member member)
        {
            return member.IsProperty && member.IsPubliclyWritable;
        }

        public virtual string GetTableName(Type type)
        {
            var att = type.GetCustomAttributes(true).OfType<TableAttribute>().SingleOrDefault();
            if (att != null)
            {
                return att.TableName;
            }
            return type.Name;
        }

        public virtual bool ShouldMapTable(Type tableType)
        {
            return tableType.IsClass && !tableType.IsAbstract && !tableType.IsArray
                && tableType.Namespace != typeof(int).Namespace;
        }

        public virtual bool ShouldMapRelationship(Member member)
        {
            return ShouldMapColumn(member);
        }
    }
}
